#ifndef PUB_LIB_H
#define PUB_LIB_H

#include "raylib.h"
#include "raymath.h"

//if print debug information
//#define DEBUG_VER

#define sampled_point(color) (color.a)

/* vertex type */
enum vertex_type{
	VERTEX4 = 1, //Quaternion
	VERTEX3, //Vector3
	VERTEX2 //Vector3
};

/* Quaternion to vector3
 * Vector3 dst;
 * Quaternion src;
 * */
#define QuadToV3(dst, src) {\
	(dst).x = (src).x; \
	(dst).y = (src).y; \
	(dst).z = (src).z; \
}

/* vector3 to Quaternion
 * Quaternion dst;
 * Vector3 src;
 * w = val
 * */
#define to_vec4(dst, src, value) {\
	(dst).x = (src).x; \
	(dst).y = (src).y; \
	(dst).z = (src).z; \
	(dst).w = value; \
}

#ifndef WIN32
#define max(a,b) (a < b ? b : a)
#define min(a,b) (a < b ? a : b)
#endif

//swap 2 float number
#define swapf(a, b) {\
	float tempf = a; \
	a = b; \
	b = tempf; \
}

//swap 2 int number
#define swapi(a, b) {\
	int temp = a; \
	a = b; \
	b = temp; \
}

//Vector3: 3 * 1
extern void print_vector(char* name, Vector3 v);

//quaternion: 4 * 1
extern void print_qm(char* name, Quaternion v);

/* 3 * 3 matrix */
extern void print_matrix3(char* name, Matrix mat);

/* 4 * 4 matrix */
extern void print_mat(char* name, Matrix mat);

#define matrxiMul(a, b) MatrixMultiply(b, a)

/*
 * a,b,c is apex of triangle
 * return 1 if clockwise
 * return 0 if anticlockwise
 * */
extern int is_clockwise(Vector3 a, Vector3 b, Vector3 c);

extern int is_clockwiseQ(Quaternion v0, Quaternion v1, Quaternion v2);

/* get the bounding box of triangle (a, b, c) */
extern BoundingBox calcBoundingBox(Vector3 a, Vector3 b, Vector3 c);

/* index of point(x,y) */
extern int get_point_index(int x, int y, int width, int height);

extern Color makeRGBA(Vector3 v);
extern Color toColor(Vector3 color);

extern Vector3 barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c);

//init 3 vertices of a triangle
extern void init_triangle_points(float* val, void* dest, enum vertex_type type);

//result[3] = ori[3] transform by matrix m
extern void trans_point(Vector3* result, Quaternion* ori, Matrix m);

//ensure v is in [low, high]
extern float clampf(const float low, const float high, const float v);

extern bool solveQuadratic(const float a, const float b, const float c, float* x0, float* x1);

//get bounding box
extern Vector3 get_min(Vector3 a, Vector3 b);//get min (x,y,z) of a,b
extern Vector3 get_max(Vector3 a, Vector3 b);//get max (x,y,z) of a,b

extern void UpdateProgress(float progress);

/*
 * call me after BeginDrawing();
*/
extern void draw_model(Model* m, Vector3 eye, float fov, float scale);

/*
 * call me after BeginDrawing();
 * background color is white
 * model color is black
*/
extern void draw_modelEx(Model* m, Vector3 eye, float fov, float scale,
	Vector3 axis, float angle);

/* other */
#define ESC_KEY 27


#endif
